﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;
using System.Diagnostics;
using MixScript.DBService;
using MixScript.BLL;
using System.Data;

namespace MixScriptWeb
{



    public class XMLMenuList
    {
        #region Delegates

        public delegate void MenuAccessRequired(object sender, MenuAccessEventArgs args);

        #endregion

        private const string LOGOUT_STRING = "Logout";

        private string _DataFile;
        private string _ErrorReturn;
        private Page _page;
        private string _PathNode;
        private string _xmlMapping;
        private string currUser;
       
        
        public string ErrorReturn
        {
            get { return _ErrorReturn; }
        }

        public string PathNode
        {
            get { return _PathNode; }
            set { _PathNode = value; }
        }

        public string XmlMapping
        {
            get { return _xmlMapping; }
            set { _xmlMapping = value; }
        }

        public string DataFile
        {
            get { return _DataFile; }
            set { _DataFile = value; }
        }

        public string CurrentUser
        {
            get { return currUser; }
            set { currUser = value; }
        }

        public Page CurrentPage
        {
            get { return _page; }
            set { _page = value; }
        }

        public ulong EffectivePermission { get; set; }

        public TreeNode[] GetTreeNodeMenus
        {
            get
            {
                TreeNode tn = null;
                //TreeNode[] tns = null;
                List<TreeNode> lstNodes = new List<TreeNode>();
                XmlDataSource xds = new XmlDataSource();
                XmlDocument xmlD = null;
                XmlNode xmlN = null;

                _ErrorReturn = string.Empty;

                try
                {
                    if (!string.IsNullOrEmpty(_xmlMapping))
                    {
                        xmlD = new XmlDocument();
                        xmlD.LoadXml(_xmlMapping);
                    }
                    else
                    {
                        xds.DataFile = _DataFile;
                        xmlD = xds.GetXmlDocument();
                    }
                    xmlN = xmlD.SelectSingleNode(_PathNode).FirstChild;
                    while (xmlN != null)
                    {
                        if ((xmlN.NodeType == XmlNodeType.Element) ||
                            ((xmlN.NodeType == XmlNodeType.Comment) && (xmlN.Value.Trim().CompareTo("Separator") == 0)))
                        {
                            tn = TreeViewRecursive(null, xmlN);
                            if (tn != null)
                            {
                                if ((tn.ChildNodes.Count > 0) && (tn.SelectAction == TreeNodeSelectAction.None))
                                {
                                    tn.SelectAction = TreeNodeSelectAction.Expand;
                                }

                                lstNodes.Add(tn);
                            }
                        }

                        xmlN = xmlN.NextSibling;
                    }
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(
                      string.Format("KSEIMainMenu:XMLMenuList:GetTreeNodeMenus - {0}", ex.Message));

                    _ErrorReturn = ex.Message;
                }

                xmlN = null;
                xmlD = null;
                if (xds != null)
                {
                    xds.Dispose();
                    xds = null;
                }

                GC.Collect();

                return lstNodes.ToArray();
            }
        }

        public event MenuAccessRequired MenuAccessing;

        private bool OnMenuRequiredAllow(string menuName, string menuAccess, ref string menuUrl)
        {
            bool isOk = false;
            string localUrl = menuUrl;

            if (MenuAccessing != null)
            {
                MenuAccessEventArgs mnu = new MenuAccessEventArgs(menuName, menuAccess);
                mnu.MenuUrl = localUrl;
                MenuAccessing(this, mnu);

                isOk = mnu.IsAllowed;
            }

            return isOk;
        }

        private string getFromAttributes(XmlAttributeCollection xac, string nameKey)
        {
            if (xac.Count < 1)
                return string.Empty;

            string sret = string.Empty;
            try
            {
                foreach (XmlAttribute xa in xac)
                {
                    if (xa.Name == nameKey)
                        sret = XmlConvert.DecodeName(xa.Value);
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(
                  string.Format("KSEIMainMenu:XMLMenuList:getFromAttributes - {0}", ex.Message));

                sret = string.Empty;
            }

            return sret.Trim();
        }

        private TreeNode TreeViewRecursive(TreeNode tn, XmlNode xmlN)
        {
            
            string s;
            //int nMod;
            bool bNodeRoot = false;
            //bool isChildExist = false;
            TreeNode tnC;

            //n = 0;
            //nMod = 0;
            while (xmlN != null)
            {
              
                if ((xmlN.NodeType == XmlNodeType.Element) ||
                    ((xmlN.NodeType == XmlNodeType.Comment) && (xmlN.Value.Trim().CompareTo("Separator") == 0)))
                {
                    if (getFromAttributes(xmlN.Attributes, "nodeid").ToString().Trim() == "111")
                    {
                        //xmlN = xmlN.NextSibling;
                        //if (xmlN == null)
                        //{
                        //    break;

                        //}

                        goto lanjot;
                    }

                    if (tn == null)
                    {
                        tn = new TreeNode();
                        bNodeRoot = true;
                        tnC = tn;
                    }
                    else
                    {
                        tnC = new TreeNode();
                        bNodeRoot = false;
                    }

                    if (xmlN.NodeType == XmlNodeType.Comment)
                        goto NextNode;

                    //s = xmlN.Attributes["url"].Value.Trim();

                    tnC.Text = getFromAttributes(xmlN.Attributes, "title"); //xmlN.Attributes["title"].Value.Trim();
                    tnC.Value = getFromAttributes(xmlN.Attributes, "nodeid");
                    tnC.ToolTip = getFromAttributes(xmlN.Attributes, "description"); //xmlN.Attributes["description"].Value;
                  //  tnC.ImageUrl = "dfg";

                    if (_page != null)
                    {
                        s = getFromAttributes(xmlN.Attributes, "url");
                        if (!string.IsNullOrEmpty(s))
                        {
                            if (string.Compare(tnC.Text, LOGOUT_STRING, StringComparison.OrdinalIgnoreCase) == 0)
                            {
                                s = string.Format(s, currUser);
                            }

                            s = string.Format("javascript:location.replace('{0}');",
                                              _page.ResolveClientUrl(s));
                        }
                    }
                    else
                    {
                        s = getFromAttributes(xmlN.Attributes, "url");

                        if (string.Compare(tnC.Text, LOGOUT_STRING, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            s = string.Format(s, currUser);
                        }
                    }

                    if (s.Length > 0)
                        tnC.NavigateUrl = s;
                    else
                        tnC.SelectAction = TreeNodeSelectAction.None;

                    string sMode = getFromAttributes(xmlN.Attributes, "mode");
                    string sMap = getFromAttributes(xmlN.Attributes, "mapping");

                    if (sMap.Length > 0)
                    {
                        bool bOk = true; //OnMenuRequiredAllow(sMap, sMode, ref s);

                        if (!bOk)
                        {
                            if (bNodeRoot)
                            {
                                tn.ChildNodes.Clear();
                                tn = null;
                                break;
                            }
                            else
                            {
                                tnC.ChildNodes.Clear();
                                tnC = null;
                                
                            }
                            //break;
                        }
                        else
                        {
                            tnC.NavigateUrl = s;
                        }
                    }

                NextNode:
                   
                    if (xmlN.HasChildNodes)
                    {
                        //isChildExist = true;
                        tnC = TreeViewRecursive(tnC, xmlN.FirstChild);
                        
                        
                        if ( (tnC != null) && (tnC.ChildNodes.Count > 0) )
                            tn.ChildNodes.Add(tnC);
                        else
                            tn = null;
                       
                    }
                    else
                    {
                        if (bNodeRoot)
                            break;

                        if ((xmlN.NodeType != XmlNodeType.Comment) && (tnC != null))
                            tn.ChildNodes.Add(tnC);
                    }

                    if ((xmlN == null) || bNodeRoot)
                        break;
                }
            lanjot:
                xmlN = xmlN.NextSibling;
            }

            GC.Collect();

            return tn;
        
        }
    }

    public class MenuAccessEventArgs : EventArgs
    {
        private readonly string mnuAccess;
        private readonly string mnuName;

        public MenuAccessEventArgs(string menuName, string menuAccess)
        {
            mnuName = menuName;
            mnuAccess = menuAccess;
        }

        public bool IsAllowed { get; set; }

        public string MenuName
        {
            get { return mnuName; }
        }

        public string MenuAccess
        {
            get { return mnuAccess; }
        }

        public string MenuUrl { get; set; }
    }

    [Serializable]
    public class UserMenuAccess
    {
        private readonly IDictionary<string, GroupAccessList> dicColl;

        public UserMenuAccess()
        {
            dicColl = new Dictionary<string, GroupAccessList>(StringComparer.CurrentCultureIgnoreCase);
        }

        public string UserName { get; set; }

        ~UserMenuAccess()
        {
            if (dicColl != null)
            {
                dicColl.Clear();
            }
        }

        public bool GroupExist(string groupName)
        {
            return dicColl.ContainsKey(groupName);
        }

        public GroupAccessList AddGroupAccess(string groupName)
        {
            if (GroupExist(groupName))
                return null;
            GroupAccessList gal = new GroupAccessList();
            dicColl.Add(groupName, gal);

            return gal;
        }

        public GroupAccessList GetGroupAccess(string groupName)
        {
            if (!GroupExist(groupName))
                return null;

            return dicColl[groupName];
        }

        public void AddGroupAccessList(string groupName, string mappingName, string listGroup)
        {
            if (!GroupExist(groupName))
                return;

            GroupAccessList ga = dicColl[groupName];
            //ga.GroupAccessList(mappingName, listGroup);
        }

        public string GetGroupAccessList(string groupName, string mappingName)
        {
            return string.Empty;
        }

        public bool SearchInAccessList(string groupName, string data)
        {
            if ((groupName.Length < 1) ||
                (data.Length < 1) ||
                (!GroupExist(groupName)))
                return false;

            GroupAccessList gal = dicColl[groupName];

            return gal.SearchInAccessList(data);
        }

        public bool SearchInAccessPageList(string groupName, string groupKey)
        {
            if (!GroupExist(groupName))
                return false;

            GroupAccessList gal = dicColl[groupName];
            string sKey = gal.SearchInAccessPageList(groupKey);

            return SearchInAccessList(groupName, sKey);
        }

        public bool IsContainAccess(string groupName)
        {
            if (!GroupExist(groupName))
                return false;

            GroupAccessList gal = dicColl[groupName];
            return gal.IsContainAccess;
        }

        public void ClearAll()
        {
            if ((dicColl != null) && (dicColl.Count > 0))
            {
                foreach (KeyValuePair<string, GroupAccessList> kvp in dicColl)
                {
                    GroupAccessList gal = kvp.Value;
                    gal.ClearAll();
                }
            }
        }
    }

    [Serializable]
    public class GroupAccessList
    {
        private readonly IDictionary<string, string> accessList;
        private readonly IDictionary<string, string> accessPage;
        private bool isAdmin;

        public GroupAccessList()
        {
            accessList = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
            accessPage = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
        }

        public bool IsAdmin
        {
            get { return isAdmin; }
        }

        public bool IsContainAccess
        {
            get { return (accessList.Count > 0); }
        }

        ~GroupAccessList()
        {
            if (accessList != null)
                accessList.Clear();
            if (accessPage != null)
                accessPage.Clear();
        }

        public void AddAccessLists(string key, string access)
        {
            if ((string.Compare(key, "admin", StringComparison.OrdinalIgnoreCase) == 0) && (!isAdmin))
                isAdmin = true;

            accessList.Add(key, access);
        }

        public void AddPageLists(string key, string access)
        {
            if (!accessPage.ContainsKey(key))
                accessPage.Add(key, access);
        }

        public bool HasKey(string key)
        {
            return accessList.ContainsKey(key);
        }

        public string SearchInAccessPageList(string criteria)
        {
            if (!accessPage.ContainsKey(criteria))
                return string.Empty;

            return accessPage[criteria];
        }

        public bool SearchInAccessList(string criteria)
        {
            bool bFound = false;
            foreach (KeyValuePair<string, string> kvp in accessList)
            {
                bFound = kvp.Value.Contains(criteria);
                if (bFound)
                    break;
            }
            return bFound;
        }

        public void ClearAll()
        {
            if ((accessList != null) && (accessList.Count > 0))
            {
                accessList.Clear();
            }
        }
    }

    public class ExtractRightMenu : cBaseBLL
    {
        private readonly UserMenuAccess uma;
        private string errString;
        private string thisUser;
        private string xmlMapping;// = "MixScript/MAINMENU";//"KSEICBEST/MAINMENU";
        private DataTable _dtPriv;

        public DataTable DtPriv
        {
            get { return _dtPriv; }
            // set { _dtPriv = value; }
        }

        public bool getPriv(string uid)
        {
            try
            {

                string ssql = "exec getmenu @username='" + uid + "'";
                _dtPriv = new DataTable();
                _dtPriv = Dbserver.ExecuteQuery(ssql, "");

                return DtPriv.Rows.Count > 0;
            }
            catch (Exception ex)
            {

                throw ex;
            }

        }
        public ExtractRightMenu()
        {
            // uma = userMenu;
            thisUser = "current";
        }

        public ExtractRightMenu(string uid)
        {
            thisUser = uid;
            getPriv(uid);
        }

        public string CurrentUser
        {
            get { return thisUser; }
            set { thisUser = value; }
        }

        public string XmlMapping
        {
            get { return xmlMapping; }
            set { xmlMapping = value; }
        }

        public string ErrorReturn
        {
            get { return errString; }
        }

        public TreeNode[] AksesMenu(string xPath, Page page)
        {
            // if (string.IsNullOrEmpty(xPath) || (uma == null))
            //   return null;

            XMLMenuList myMenu = new XMLMenuList();
            myMenu.MenuAccessing += myMenu_MenuAccessing;
            myMenu.CurrentPage = page;
            myMenu.CurrentUser = thisUser.Trim().ToLower();
            myMenu.DataFile = "..\\App_Data\\config\\tvMenu.xml";
            //string.Format("{0}XMLMenu.xml", CStaticConfig.StructureAppSettings.MappedDir);
            myMenu.PathNode = xPath;
            myMenu.XmlMapping = xmlMapping;
            //myMenu.EffectivePermission = 1;
            TreeNode[] tns = myMenu.GetTreeNodeMenus;
            if ((tns != null) && (tns.Length > 0))
            {
                ;
            }
            else
            {
                errString = myMenu.ErrorReturn;
            }

            myMenu.MenuAccessing -= myMenu_MenuAccessing;
            myMenu = null;

            GC.Collect();

            return tns;
        }

        private void myMenu_MenuAccessing(object sender, MenuAccessEventArgs args)
        {
            //throw new NotImplementedException();
            if (uma != null)
            {
                GroupAccessList gal = null;
                if (args.MenuName.Contains(";"))
                {
                    string[] splt = args.MenuName.Split(new[] { ';' });
                    foreach (string s in splt)
                    {
                        if (uma.IsContainAccess(s))
                        {
                            gal = uma.GetGroupAccess(s);
                            break;
                        }
                    }
                }
                else
                    gal = uma.GetGroupAccess(args.MenuName);

                if (gal == null)
                    args.IsAllowed = false;
                else
                {
                    if (gal.IsAdmin)
                    {
                        args.IsAllowed = true;
                        return;
                    }

                    if (gal.IsContainAccess)
                    {
                        if (args.MenuAccess.Length < 1)
                            args.IsAllowed = true;
                        else
                        {
                            string[] splt = args.MenuAccess.Split(new[] { ';' });
                            bool bOk = false;
                            foreach (string s in splt)
                            {
                                if (s.Trim().Length > 0)
                                {
                                    bOk = gal.SearchInAccessList(s);
                                    if (bOk)
                                        break;
                                }
                            }
                            args.IsAllowed = bOk;
                        }
                    }
                    else
                        args.IsAllowed = false;
                }
            }
        }

        public static bool IsUserHaveAccess(UserMenuAccess userMenu, string mapString, string accessCode)
        {
            bool accOk = false;

            if (userMenu != null)
            {
                GroupAccessList gal = gal = userMenu.GetGroupAccess(mapString);

                if (gal == null)
                    accOk = false;
                else
                {
                    if (gal.IsContainAccess)
                    {
                        if (string.IsNullOrEmpty(accessCode))
                            accOk = false;
                        else
                        {
                            string[] splt = accessCode.Split(new[] { ';' });
                            foreach (string s in splt)
                            {
                                if (s.Trim().Length > 0)
                                {
                                    accOk = gal.SearchInAccessList(s);
                                    if (accOk)
                                        break;
                                }
                            }
                        }
                    }
                    else
                        accOk = false;
                }
            }

            return accOk;
        }
    }

}